﻿namespace MefContrib.Models.Provider
{
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Primitives;
    using System.Reflection;

    /// <summary>
    /// 
    /// </summary>
    public static class MemberInfoExtensions
    {
        /// <summary>
        /// Returns the cardinality of the provided member.
        /// </summary>
        /// <param name="member"></param>
        /// <param name="allowDefault"><see langword="true" /> if the default value of the member can be used if no exports match; otherwise <see langword="false" />.</param>
        /// <returns></returns>
        public static ImportCardinality GetCardinality(this MemberInfo member, bool allowDefault)
        {
            // TODO: This can't be right? A field should be able to act as an import
            var propertyInfo = member as PropertyInfo;
            if (propertyInfo != null)
            {
                if (propertyInfo.PropertyType.IsEnumerable())
                {
                    return ImportCardinality.ZeroOrMore;
                }

                return (allowDefault) ?
                    ImportCardinality.ZeroOrOne : ImportCardinality.ExactlyOne;
            }

            var fieldInfo = member as FieldInfo;
            if (fieldInfo != null)
            {
                if (fieldInfo.FieldType.IsEnumerable())
                {
                    return ImportCardinality.ZeroOrMore;
                }

                return (allowDefault) ?
                    ImportCardinality.ZeroOrOne : ImportCardinality.ExactlyOne;
            }

            throw new ImportCardinalityMismatchException();
        }

        /// <summary>
        /// Creates a <see cref="ComposableMember"/> for the specified <see cref="MemberInfo"/> instance.
        /// </summary>
        /// <param name="member">The <see cref="MemberInfo"/> instance to create the <see cref="ComposableMember"/> for.</param>
        /// <returns>A <see cref="ComposableMember"/> instance.</returns>
        public static ComposableMember ToComposableMember(this MemberInfo member)
        {
            return ComposableMember.Create(member);
        }
    }
}